﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using System.Text.RegularExpressions;

namespace Spider
{
    public class ScrapWorker
    {
        /// <summary>
        /// Common Object
        /// </summary>
        private Util mUtil;

        /// <summary>
        /// product's url
        /// </summary>
        private Uri m_ProUri;

        /// <summary>
        /// The thread that is being used.
        /// </summary>
        private Thread m_thread;

        private string mThreadName;

        IRequest request;

        public Uri ObtainProURI()
        {
            Monitor.Enter(this);
            while (mUtil.QueueProduct.Count < 1)
            {
                //Monitor.Wait(QueueProduct, 100);
                Thread.Sleep(100);
            }
            Uri next = null;

            next = (Uri)mUtil.QueueProduct.Dequeue();

            Monitor.Pulse(this);

            Monitor.Exit(this);

            return next;
        }

        /// <summary>
        /// constructor
        /// </summary>
        /// <param name="util"></param>
        public ScrapWorker(Util util, string ThreadName)
        {
            mUtil = util;
            mThreadName = ThreadName;
        }

        /// <summary>
        /// This method is the main loop for the scrapping threads.
        /// </summary>
        private void Process()
        {
            mUtil.done.WorkerBegin();
            request = new HttpRequestSyn();
            //request.GetResponseComplete += new RequestByHttp.GetCompleteHandler(request_GetResponseComplete);

            while (!mUtil.AbortTag)
            {
                m_ProUri = null;
                m_ProUri = ObtainProURI();
                if (m_ProUri == null)
                {
                    //Thread.Sleep(1000);
                    continue;
                }

                mUtil.modifyProductURIStatus(m_ProUri, Status.STATUS_QUEUEDING);

                try
                {
                    request_GetResponseComplete(request.GetPage(m_ProUri));                        
                }
                catch
                {
                    mUtil.modifyProductURIStatus(m_ProUri, Status.STATUS_FAILED);
                }
            }
            request.Dispose();
            mUtil.done.WorkerEnd();
        }

        void request_GetResponseComplete(PageClass Page)
        {
            if (Page == null)
                return;

            if (Page != null)
            {
                ParseProduction(Page.html, Page.URL);
                mUtil.modifyProductURIStatus(Page.URL, Status.STATUS_SUCCESS);
            }
            else
            {
                mUtil.modifyProductURIStatus(Page.URL, Status.STATUS_FAILED);
            }
        }

        /// <summary>
        /// Find the product's infos in the htmlsource
        /// </summary>
        /// <param name="HTML">htmlsource</param>
        /// <param name="ProUri">The page url</param>
        private void ParseProduction(string HTML, Uri ProUri)
        {
            if (mUtil.AbortTag) return;//stop;
            //Monitor.Enter(this);
            Product pro = new Product();
            Match n;
            if (DataHandler.Instance.CurrentRule == null)
                return;
            Regex regexTitle = new Regex(DataHandler.Instance.CurrentRule.TitleRegex, RegexOptions.Singleline);
            Regex regexDescript = new Regex(DataHandler.Instance.CurrentRule.DescriptionRegex, RegexOptions.Singleline);
            Regex regexImageUrl = new Regex(DataHandler.Instance.CurrentRule.ImageUrlRegex, RegexOptions.Singleline);
            Regex regexPrice = new Regex(DataHandler.Instance.CurrentRule.PriceRegex, RegexOptions.Singleline);
            string tempStr;
            n = regexTitle.Match(HTML);
            tempStr = Regex.Replace(n.Groups[1].Value, @"<.*?>", "").Trim();
            pro.Title = tempStr;

            n = regexDescript.Match(HTML);
            pro.Description = ProcessString(n.Groups[1].Value);

            n = regexImageUrl.Match(HTML);
            string ImgUrl = n.Groups[1].Value;
            if (!string.IsNullOrEmpty(ImgUrl)&&!ImgUrl.Contains("http://"))
            {
                ImgUrl = "http://" + ProUri.Host + ImgUrl;
            }
            pro.ImageURL = ImgUrl;

            n = regexPrice.Match(HTML);
            tempStr = Regex.Replace(n.Groups[1].Value, @"<.*?>", "").Trim();
            tempStr=Regex.Replace(tempStr, @"Was: .*?Now: ", "");
            pro.Price = tempStr;
            pro.URL = ProUri.ToString();
            if (string.IsNullOrEmpty(pro.Title) ||
                string.IsNullOrEmpty(pro.Description) ||
                string.IsNullOrEmpty(pro.Price) ||
                string.IsNullOrEmpty(pro.ImageURL))
            {
                mUtil.UnParserProductUrl.Enqueue(ProUri);
            }
            else
            {
                if (mUtil.AbortTag) return;//stop;
                //mUtil.InfoForm.addProductions(pro);
                mUtil.addProduct(pro);
            }
            mUtil.showMsg();
            //Monitor.Exit(this);
        }

        /// <summary>
        /// Start the Scrapping
        /// </summary>
        public void Start()
        {
            ThreadStart ts = new ThreadStart(this.Process);
            m_thread = new Thread(ts);
            m_thread.Name = mThreadName;
            m_thread.IsBackground = true;
            //m_thread.Priority = ThreadPriority.Normal;
            m_thread.Start();
            Log.Instance.WriteMsg(string.Format("ScrapWorker Thread Name:{0} Thraad State:{1}", AppDomain.GetCurrentThreadId(), Thread.CurrentThread.ThreadState.ToString()));

        }

        public Thread MThread
        {
            get { return m_thread; }
        }

        public Uri ProURI
        {
            get { return m_ProUri; }
        }
        public string ProcessString(string input)
        {
            string tempStr;
            tempStr = Regex.Replace(input, @"<[^(br)^(li)].*?>", "", RegexOptions.IgnoreCase).Trim();
            tempStr = Regex.Replace(tempStr, @"\s\s+?", "");
            tempStr = tempStr.Replace("<b>", "");
            return tempStr;
        }
    }
}
